1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21
22 import com.google.common.annotations.Beta;
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.base.Function;
25 import com.google.common.base.Objects;
26 import com.google.common.base.Supplier;
27 import com.google.common.collect.Table.Cell;
28
29 import java.io.Serializable;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.Iterator;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.SortedMap;
36 import java.util.SortedSet;
37
38 import javax.annotation.Nullable;
39
40
41
42
43
44
45
46
47
48
49
50
51 @GwtCompatible
52 public final class Tables {
53 private Tables() {}
54
55
56
57
58
59
60
61
62
63
64
65 public static <R, C, V> Cell<R, C, V> immutableCell(
66 @Nullable R rowKey, @Nullable C columnKey, @Nullable V value) {
67 return new ImmutableCell<R, C, V>(rowKey, columnKey, value);
68 }
69
70 static final class ImmutableCell<R, C, V>
71 extends AbstractCell<R, C, V> implements Serializable {
72 private final R rowKey;
73 private final C columnKey;
74 private final V value;
75
76 ImmutableCell(
77 @Nullable R rowKey, @Nullable C columnKey, @Nullable V value) {
78 this.rowKey = rowKey;
79 this.columnKey = columnKey;
80 this.value = value;
81 }
82
83 @Override
84 public R getRowKey() {
85 return rowKey;
86 }
87 @Override
88 public C getColumnKey() {
89 return columnKey;
90 }
91 @Override
92 public V getValue() {
93 return value;
94 }
95
96 private static final long serialVersionUID = 0;
97 }
98
99 abstract static class AbstractCell<R, C, V> implements Cell<R, C, V> {
100
101 AbstractCell() {}
102
103 @Override public boolean equals(Object obj) {
104 if (obj == this) {
105 return true;
106 }
107 if (obj instanceof Cell) {
108 Cell<?, ?, ?> other = (Cell<?, ?, ?>) obj;
109 return Objects.equal(getRowKey(), other.getRowKey())
110 && Objects.equal(getColumnKey(), other.getColumnKey())
111 && Objects.equal(getValue(), other.getValue());
112 }
113 return false;
114 }
115
116 @Override public int hashCode() {
117 return Objects.hashCode(getRowKey(), getColumnKey(), getValue());
118 }
119
120 @Override public String toString() {
121 return "(" + getRowKey() + "," + getColumnKey() + ")=" + getValue();
122 }
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 public static <R, C, V> Table<C, R, V> transpose(Table<R, C, V> table) {
140 return (table instanceof TransposeTable)
141 ? ((TransposeTable<R, C, V>) table).original
142 : new TransposeTable<C, R, V>(table);
143 }
144
145 private static class TransposeTable<C, R, V> extends AbstractTable<C, R, V> {
146 final Table<R, C, V> original;
147
148 TransposeTable(Table<R, C, V> original) {
149 this.original = checkNotNull(original);
150 }
151
152 @Override
153 public void clear() {
154 original.clear();
155 }
156
157 @Override
158 public Map<C, V> column(R columnKey) {
159 return original.row(columnKey);
160 }
161
162 @Override
163 public Set<R> columnKeySet() {
164 return original.rowKeySet();
165 }
166
167 @Override
168 public Map<R, Map<C, V>> columnMap() {
169 return original.rowMap();
170 }
171
172 @Override
173 public boolean contains(
174 @Nullable Object rowKey, @Nullable Object columnKey) {
175 return original.contains(columnKey, rowKey);
176 }
177
178 @Override
179 public boolean containsColumn(@Nullable Object columnKey) {
180 return original.containsRow(columnKey);
181 }
182
183 @Override
184 public boolean containsRow(@Nullable Object rowKey) {
185 return original.containsColumn(rowKey);
186 }
187
188 @Override
189 public boolean containsValue(@Nullable Object value) {
190 return original.containsValue(value);
191 }
192
193 @Override
194 public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
195 return original.get(columnKey, rowKey);
196 }
197
198 @Override
199 public V put(C rowKey, R columnKey, V value) {
200 return original.put(columnKey, rowKey, value);
201 }
202
203 @Override
204 public void putAll(Table<? extends C, ? extends R, ? extends V> table) {
205 original.putAll(transpose(table));
206 }
207
208 @Override
209 public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
210 return original.remove(columnKey, rowKey);
211 }
212
213 @Override
214 public Map<R, V> row(C rowKey) {
215 return original.column(rowKey);
216 }
217
218 @Override
219 public Set<C> rowKeySet() {
220 return original.columnKeySet();
221 }
222
223 @Override
224 public Map<C, Map<R, V>> rowMap() {
225 return original.columnMap();
226 }
227
228 @Override
229 public int size() {
230 return original.size();
231 }
232
233 @Override
234 public Collection<V> values() {
235 return original.values();
236 }
237
238
239 private static final Function<Cell<?, ?, ?>, Cell<?, ?, ?>> TRANSPOSE_CELL =
240 new Function<Cell<?, ?, ?>, Cell<?, ?, ?>>() {
241 @Override
242 public Cell<?, ?, ?> apply(Cell<?, ?, ?> cell) {
243 return immutableCell(
244 cell.getColumnKey(), cell.getRowKey(), cell.getValue());
245 }
246 };
247
248 @SuppressWarnings("unchecked")
249 @Override
250 Iterator<Cell<C, R, V>> cellIterator() {
251 return Iterators.transform(original.cellSet().iterator(), (Function) TRANSPOSE_CELL);
252 }
253 }
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296 @Beta
297 public static <R, C, V> Table<R, C, V> newCustomTable(
298 Map<R, Map<C, V>> backingMap, Supplier<? extends Map<C, V>> factory) {
299 checkArgument(backingMap.isEmpty());
300 checkNotNull(factory);
301
302 return new StandardTable<R, C, V>(backingMap, factory);
303 }
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 @Beta
332 public static <R, C, V1, V2> Table<R, C, V2> transformValues(
333 Table<R, C, V1> fromTable, Function<? super V1, V2> function) {
334 return new TransformedTable<R, C, V1, V2>(fromTable, function);
335 }
336
337 private static class TransformedTable<R, C, V1, V2>
338 extends AbstractTable<R, C, V2> {
339 final Table<R, C, V1> fromTable;
340 final Function<? super V1, V2> function;
341
342 TransformedTable(
343 Table<R, C, V1> fromTable, Function<? super V1, V2> function) {
344 this.fromTable = checkNotNull(fromTable);
345 this.function = checkNotNull(function);
346 }
347
348 @Override public boolean contains(Object rowKey, Object columnKey) {
349 return fromTable.contains(rowKey, columnKey);
350 }
351
352 @Override public V2 get(Object rowKey, Object columnKey) {
353
354
355 return contains(rowKey, columnKey)
356 ? function.apply(fromTable.get(rowKey, columnKey)) : null;
357 }
358
359 @Override public int size() {
360 return fromTable.size();
361 }
362
363 @Override public void clear() {
364 fromTable.clear();
365 }
366
367 @Override public V2 put(R rowKey, C columnKey, V2 value) {
368 throw new UnsupportedOperationException();
369 }
370
371 @Override public void putAll(
372 Table<? extends R, ? extends C, ? extends V2> table) {
373 throw new UnsupportedOperationException();
374 }
375
376 @Override public V2 remove(Object rowKey, Object columnKey) {
377 return contains(rowKey, columnKey)
378 ? function.apply(fromTable.remove(rowKey, columnKey)) : null;
379 }
380
381 @Override public Map<C, V2> row(R rowKey) {
382 return Maps.transformValues(fromTable.row(rowKey), function);
383 }
384
385 @Override public Map<R, V2> column(C columnKey) {
386 return Maps.transformValues(fromTable.column(columnKey), function);
387 }
388
389 Function<Cell<R, C, V1>, Cell<R, C, V2>> cellFunction() {
390 return new Function<Cell<R, C, V1>, Cell<R, C, V2>>() {
391 @Override public Cell<R, C, V2> apply(Cell<R, C, V1> cell) {
392 return immutableCell(
393 cell.getRowKey(), cell.getColumnKey(),
394 function.apply(cell.getValue()));
395 }
396 };
397 }
398
399 @Override
400 Iterator<Cell<R, C, V2>> cellIterator() {
401 return Iterators.transform(fromTable.cellSet().iterator(), cellFunction());
402 }
403
404 @Override public Set<R> rowKeySet() {
405 return fromTable.rowKeySet();
406 }
407
408 @Override public Set<C> columnKeySet() {
409 return fromTable.columnKeySet();
410 }
411
412 @Override
413 Collection<V2> createValues() {
414 return Collections2.transform(fromTable.values(), function);
415 }
416
417 @Override public Map<R, Map<C, V2>> rowMap() {
418 Function<Map<C, V1>, Map<C, V2>> rowFunction =
419 new Function<Map<C, V1>, Map<C, V2>>() {
420 @Override public Map<C, V2> apply(Map<C, V1> row) {
421 return Maps.transformValues(row, function);
422 }
423 };
424 return Maps.transformValues(fromTable.rowMap(), rowFunction);
425 }
426
427 @Override public Map<C, Map<R, V2>> columnMap() {
428 Function<Map<R, V1>, Map<R, V2>> columnFunction =
429 new Function<Map<R, V1>, Map<R, V2>>() {
430 @Override public Map<R, V2> apply(Map<R, V1> column) {
431 return Maps.transformValues(column, function);
432 }
433 };
434 return Maps.transformValues(fromTable.columnMap(), columnFunction);
435 }
436 }
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453 public static <R, C, V> Table<R, C, V> unmodifiableTable(
454 Table<? extends R, ? extends C, ? extends V> table) {
455 return new UnmodifiableTable<R, C, V>(table);
456 }
457
458 private static class UnmodifiableTable<R, C, V>
459 extends ForwardingTable<R, C, V> implements Serializable {
460 final Table<? extends R, ? extends C, ? extends V> delegate;
461
462 UnmodifiableTable(Table<? extends R, ? extends C, ? extends V> delegate) {
463 this.delegate = checkNotNull(delegate);
464 }
465
466 @SuppressWarnings("unchecked")
467 @Override
468 protected Table<R, C, V> delegate() {
469 return (Table<R, C, V>) delegate;
470 }
471
472 @Override
473 public Set<Cell<R, C, V>> cellSet() {
474 return Collections.unmodifiableSet(super.cellSet());
475 }
476
477 @Override
478 public void clear() {
479 throw new UnsupportedOperationException();
480 }
481
482 @Override
483 public Map<R, V> column(@Nullable C columnKey) {
484 return Collections.unmodifiableMap(super.column(columnKey));
485 }
486
487 @Override
488 public Set<C> columnKeySet() {
489 return Collections.unmodifiableSet(super.columnKeySet());
490 }
491
492 @Override
493 public Map<C, Map<R, V>> columnMap() {
494 Function<Map<R, V>, Map<R, V>> wrapper = unmodifiableWrapper();
495 return Collections.unmodifiableMap(Maps.transformValues(super.columnMap(), wrapper));
496 }
497
498 @Override
499 public V put(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) {
500 throw new UnsupportedOperationException();
501 }
502
503 @Override
504 public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
505 throw new UnsupportedOperationException();
506 }
507
508 @Override
509 public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
510 throw new UnsupportedOperationException();
511 }
512
513 @Override
514 public Map<C, V> row(@Nullable R rowKey) {
515 return Collections.unmodifiableMap(super.row(rowKey));
516 }
517
518 @Override
519 public Set<R> rowKeySet() {
520 return Collections.unmodifiableSet(super.rowKeySet());
521 }
522
523 @Override
524 public Map<R, Map<C, V>> rowMap() {
525 Function<Map<C, V>, Map<C, V>> wrapper = unmodifiableWrapper();
526 return Collections.unmodifiableMap(Maps.transformValues(super.rowMap(), wrapper));
527 }
528
529 @Override
530 public Collection<V> values() {
531 return Collections.unmodifiableCollection(super.values());
532 }
533
534 private static final long serialVersionUID = 0;
535 }
536
537
538
539
540
541
542
543
544
545
546
547
548
549 @Beta
550 public static <R, C, V> RowSortedTable<R, C, V> unmodifiableRowSortedTable(
551 RowSortedTable<R, ? extends C, ? extends V> table) {
552
553
554
555
556
557 return new UnmodifiableRowSortedMap<R, C, V>(table);
558 }
559
560 static final class UnmodifiableRowSortedMap<R, C, V> extends UnmodifiableTable<R, C, V>
561 implements RowSortedTable<R, C, V> {
562
563 public UnmodifiableRowSortedMap(RowSortedTable<R, ? extends C, ? extends V> delegate) {
564 super(delegate);
565 }
566
567 @Override
568 protected RowSortedTable<R, C, V> delegate() {
569 return (RowSortedTable<R, C, V>) super.delegate();
570 }
571
572 @Override
573 public SortedMap<R, Map<C, V>> rowMap() {
574 Function<Map<C, V>, Map<C, V>> wrapper = unmodifiableWrapper();
575 return Collections.unmodifiableSortedMap(Maps.transformValues(delegate().rowMap(), wrapper));
576 }
577
578 @Override
579 public SortedSet<R> rowKeySet() {
580 return Collections.unmodifiableSortedSet(delegate().rowKeySet());
581 }
582
583 private static final long serialVersionUID = 0;
584 }
585
586 @SuppressWarnings("unchecked")
587 private static <K, V> Function<Map<K, V>, Map<K, V>> unmodifiableWrapper() {
588 return (Function) UNMODIFIABLE_WRAPPER;
589 }
590
591 private static final Function<? extends Map<?, ?>, ? extends Map<?, ?>> UNMODIFIABLE_WRAPPER =
592 new Function<Map<Object, Object>, Map<Object, Object>>() {
593 @Override
594 public Map<Object, Object> apply(Map<Object, Object> input) {
595 return Collections.unmodifiableMap(input);
596 }
597 };
598
599 static boolean equalsImpl(Table<?, ?, ?> table, @Nullable Object obj) {
600 if (obj == table) {
601 return true;
602 } else if (obj instanceof Table) {
603 Table<?, ?, ?> that = (Table<?, ?, ?>) obj;
604 return table.cellSet().equals(that.cellSet());
605 } else {
606 return false;
607 }
608 }
609 }